﻿// owner 蒋家伟

#pragma once
#include "OwnerPtr.h"
#include "TemplateCommonUtils.h"

#define NEW_AS_OWNERPTR(CLASSNAME, ...) jsdk::OwnerPtr< CLASSNAME >(new CLASSNAME (__VA_ARGS__))
#define NEW_AS_OWNERPTR_WITH_DELETER(CLASSNAME, DELETER, ...) jsdk::OwnerPtr< CLASSNAME, DELETER >(new CLASSNAME (__VA_ARGS__), DELETER{})

namespace jsdk
{
    /// \ brief 智能指针的所有权转移
    /// \ return 传入目标的右值
    template<typename T, typename D = std::default_delete<T>>
    OwnerPtr<T, D> transformOwnerShip(OwnerPtr<T, D>& optr)
    {
        return std::move(optr);
    }

    /// \ brief  智能指针的所有权转移并cast到To类别, 如果转移失败，源对象并不会被释放，如果转移成功源对象被释放。
    /// \ note : 泛化版本
    /// \ return 返回一个目标类别
    template<typename To, typename From, typename DT = std::default_delete<To>, typename DF = std::default_delete<From>>
    OwnerPtr<To, DT> transformOwnerShipAndCast(OwnerPtr<From, DF>& optr, IS_CLASS_TYPE( !(is_define_quick_cast<To>::value && is_define_quick_cast<From>::value)))
    {
        using ToPointer = typename OwnerPtr<To, DT>::pointer;
        if (optr == nullptr)
            return nullptr;
        if (ToPointer newptr = dynamic_cast<ToPointer>(optr.get()))
        {
            optr.release();
            return OwnerPtr<To, DT>(newptr);
        }
        return nullptr;
    }

    /// \ brief  智能指针的所有权转移并cast到To类别, 如果转移失败，源对象并不会被释放，如果转移成功源对象被释放。
    /// \ note : 特化版本，如果定义了quick，则使用quick进行快速转换。
    /// \ return 返回一个目标类别
    template<typename To, typename From, typename DT = std::default_delete<To>, typename DF = std::default_delete<From>>
    OwnerPtr<To, DT> transformOwnerShipAndCast(OwnerPtr<From, DF>& optr, IS_CLASS_TYPE( is_define_quick_cast<To>::value && is_define_quick_cast<From>::value ))
    {
        using ToPointer = typename OwnerPtr<To, DT>::pointer;
        if (optr == nullptr)
            return nullptr;
        if (ToPointer newptr = quick_cast<To>(optr.get()))
        {
            optr.release();
            return OwnerPtr<To, DT>(newptr);
        }
        return nullptr;
    }

    // 类别描述 : 判断当前类别是不是智能指针
    template<typename T>
    struct is_OwnerPtr : std::false_type {
        using ValueType = T;
    };

    template<typename T, typename D>
    struct is_OwnerPtr<OwnerPtr<T, D>>:std::true_type {
        using ValueType = T;
        using DeleterType = D;
    };
}

